#pragma once
#include <iostream> 
#include<string>
#include<cstring>
#include<cerrno>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#include"log.hpp"
#include"InetAddr.hpp"
#include"ThreadPool.hpp"


#define Die(code) do{exit(code);}while(0)
#define BACKLOG 10
static const uint16_t default_port = 8080;
class Tcp_Server {
    using task_t = std::function<void()>;
    struct Thread_data{//处理线程的辅助类
        Thread_data(int sockfd,Tcp_Server* server)
            :_sockfd(sockfd),self(server)
        {}
        int _sockfd;
        Tcp_Server* self;
    };
    public:
        Tcp_Server(int port = default_port)
            :_port(port)
        {
        }
        void Init()
        {
            _listen_fd = ::socket(AF_INET,SOCK_STREAM,0);
            if(_listen_fd < 0){
                LOG(log_level::ERROR)<<"create listen socket error";
                Die(0);   
            }
            LOG(log_level::INFO)<<"create listen socket success: "<<_listen_fd;
            struct sockaddr_in server_addr;
            memset(&server_addr,0,sizeof(server_addr));
            server_addr.sin_family = AF_INET;
            server_addr.sin_port = ::htons(_port);
            server_addr.sin_addr.s_addr = INADDR_ANY;
            int n = ::bind(_listen_fd,(struct sockaddr*)(&server_addr),sizeof(server_addr));
            if(n < 0){
                LOG(log_level::ERROR)<<"bind error";
                Die(1);
            }
            LOG(log_level::INFO)<<"bind success";
            //tcp需将套接字设为监听状态,BACKLOG为最大连接数
            int ret = ::listen(_listen_fd,BACKLOG);
            if(ret < 0){
                LOG(log_level::ERROR)<<"listen error";
                Die(2);
            }
            LOG(log_level::INFO)<<"listen success,listen fd is "<<_listen_fd;   
        }   
        void Start()
        {
            _is_running = true;
            while(_is_running){
                //需要获取新链接
                struct sockaddr_in peer;//对端
                socklen_t peer_len = sizeof(peer);
                int conn_fd = ::accept(_listen_fd,(struct sockaddr*)(&peer),&peer_len);//获取新链接
                if(conn_fd < 0){
                    LOG(log_level::WARNING)<<"accept error"<<strerror(errno);
                    continue;
                }
                LOG(log_level::INFO)<<"accept a new connection,fd is "<<conn_fd;
                InetAddr client(peer);
                LOG(log_level::INFO)<<"client info: "<<client.GetIpPort();
                //多进程处理
                // pid_t id = fork();
                // if(id == 0){//child
                //     if(fork()==0){//孙子进程,结束后交给系统管理(孤儿进程)
                //         Handle(conn_fd);
                //         exit(0);
                //     }
                //     exit(0);
                // }
                // int rid = ::waitpid(id,nullptr,0);//回收子进程
                // ::close(conn_fd);//回收文件描述符
                // if(rid < 0){
                //     LOG(log_level::ERROR)<<"wait pid error";
                // }


                //多线程处理
                // pthread_t tid;
                // Thread_data *data = new Thread_data(conn_fd,this);//在堆上开辟
                // pthread_create(&tid,nullptr,Thread_Handle,data);

                //线程池处理
                task_t f = std::bind(&Tcp_Server::Handle,this,conn_fd);
                ThreadPool<task_t>::getinstance()->pushTask(f);
                // ThreadPool<task_t>::getinstance()->pushTask([this,conn_fd](){this->Handle(conn_fd);});
            }
        }
        static void* Thread_Handle(void* arg)//多线程处理函数
        {
            pthread_detach(pthread_self());//分离线程,避免主线程退出时等待子线程
            Thread_data *data = static_cast<Thread_data*>(arg);
            LOG(log_level::INFO)<<"thread handle,fd is "<<data->_sockfd;
            data->self->Handle(data->_sockfd);
            return nullptr;
        }
        void Handle(int socket)
        {
            char recv_buf[1024];
            while(true){
                // ssize_t n = ::read(socket, recv_buf, sizeof(recv_buf)-1);//read读不全
                ssize_t n = ::recv(socket, recv_buf, sizeof(recv_buf)-1,0);//recv

                if(n>0){
                    recv_buf[n] = '\0';
                    std::string echo_str = "echo: ";
                    echo_str += recv_buf;
                    // ::write(socket, echo_str.c_str(), echo_str.size());//write写不完善
                    ::send(socket, echo_str.c_str(), echo_str.size(),0);
                    LOG(log_level::INFO)<<"echo: "<<recv_buf;
                }
                else if(n==0){//客户端退出
                    LOG(log_level::INFO)<<"client quit: "<<socket;
                    break;
                }
                else{
                    break;
                }
            }    
            ::close(socket);//回收文件描述符
        }
        void Stop()
        {
            _is_running = false;
        }
        ~Tcp_Server()
        {
        }
    private:
        int _listen_fd;//监听套接字
        uint16_t _port;
        bool _is_running = false;
};
